﻿/* 
 * Copyright (c) 2010 Letwory Interactive
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -- Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * -- Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * Original contributor: Nathan Letwory
 */

using System;

namespace VerseSharp
{
    public delegate void MaterialFragmentCreateCallback(MaterialFragmentCreateCommand command);
    public delegate void MaterialFragmentDestroyCallback(MaterialFragmentCreateCommand command);

    public class MaterialFragmentCreateCommand : IVerseCommand
    {
        public CommandID ID { get { return CommandID.MaterialFragmentCreate; } }
        public uint NodeID;
        public ushort FragmentID;
        public FragmentType FragmentType;
        IMaterialFragment MaterialFragment;

        public void Deserialize(byte[] source, ref int pos)
        {
            NodeID = Utils.GetUInt32(source, ref pos);
            FragmentID = Utils.GetUInt16(source, ref pos);
            FragmentType = (FragmentType)source[pos++];
            switch (FragmentType)
            {
                case FragmentType.Color:
                    MaterialFragment = new MaterialFragmentColor();
                    break;
                case FragmentType.Light:
                    MaterialFragment = new MaterialFragmentLight();
                    break;
                case FragmentType.Reflection:
                    MaterialFragment = new MaterialFragmentReflection();
                    break;
                case FragmentType.Transparency:
                    MaterialFragment = new MaterialFragmentTransparency();
                    break;
                case FragmentType.Volume:
                    MaterialFragment = new MaterialFragmentVolume();
                    break;
                case FragmentType.Geometry:
                    MaterialFragment = new MaterialFragmentGeometry();
                    break;
                case FragmentType.Texture:
                    MaterialFragment = new MaterialFragmentTexture();
                    break;
                case FragmentType.Noise:
                    MaterialFragment = new MaterialFragmentNoise();
                    break;
                case FragmentType.Blender:
                    MaterialFragment = new MaterialFragmentBlender();
                    break;
                case FragmentType.Clamp:
                    MaterialFragment = new MaterialFragmentClamp();
                    break;
                case FragmentType.Matrix:
                    MaterialFragment = new MaterialFragmentMatrix();
                    break;
                case FragmentType.Ramp:
                    MaterialFragment = new MaterialFragmentRamp();
                    break;
                case FragmentType.Animation:
                    MaterialFragment = new MaterialFragmentAnimation();
                    break;
                case FragmentType.Alternative:
                    MaterialFragment = new MaterialFragmentAlternative();
                    break;
                case FragmentType.Output:
                    MaterialFragment = new MaterialFragmentOutput();
                    break;
            }
            if (MaterialFragment != null)
            {
                MaterialFragment.Deserialize(source, ref pos);
            }
        }

        public void Serialize(byte[] destination, ref int pos)
        {
            Utils.PutUInt32(destination, ref pos, NodeID);
            Utils.PutUInt16(destination, ref pos, FragmentID);
            if (MaterialFragment != null)
            {
                destination[pos++] = (byte)FragmentType;
                MaterialFragment.Serialize(destination, ref pos);
            }
            else // We want obviously to destroy materialfragment FragmentID
            {
                destination[pos++] = byte.MaxValue;
            }
        }
    }
}
